package we.socialcontroller.zingme;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;

import java.net.URLEncoder;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import java.util.Arrays;
import java.util.HashMap;

import we.common.CCommonHandler;


import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;

import org.json.JSONException;
import org.json.JSONObject;
import we.socialcontroller.CSocialControllerException;


public abstract class ZM_API_Common {
    private String subApi = "";
    protected String api = "";
    protected String secret = "";

    private final String VERSION = "2.0";

    private ZM_Config config;

    public ZM_API_Common(ZM_Config config, String subApi) {
        this.config = config;
        this.subApi = subApi;
        this.secret = config.secret;
        setAPI(config.apiURL);
    }

    public String getAPI() {
        return api;
    }

    public void setAPI(String api) {
        this.api = api + this.subApi;
    }

    public String callMethod(String method,
                             HashMap<String, String> args) throws CSocialControllerException {
        updateArgs(method, args);
        String respone = sendRequest(args);
        String result = parseRespone(respone);
        return result;
    }

    protected static String encryptMD5(String input) {
        byte[] defaultBytes = input.getBytes();
        try {
            MessageDigest algorithm = MessageDigest.getInstance("MD5");
            algorithm.reset();
            algorithm.update(defaultBytes);
            byte messageDigest[] = algorithm.digest();

            StringBuffer hexString = new StringBuffer();
            for (int i = 0; i < messageDigest.length; i++) {
                String hex = Integer.toHexString(0xFF & messageDigest[i]);
                if (hex.length() == 1)
                    hexString.append('0');

                hexString.append(hex);
            }


            //*** Testausgabe
            //    System.out.println("pass "+pass+"   md5 version is "+hexString.toString());
            return hexString + "";
        } catch (NoSuchAlgorithmException nsae) {
            CCommonHandler.writeErrLog(nsae);
            return null;
        }

    }

    public void updateArgs(String method, HashMap<String, String> args) {
        //args.put("api_key" ,  "5bc2df085caea1a9e280ab67aaa4fe4d");
        //args.put("v" ,  "2.0");
        //args.put("method" ,  method);

        args.put("api_key", config.apiKey);
        args.put("v", VERSION);
        args.put("method", method);

        long now = System.nanoTime();
        long ms = now / 1000;
        long nano = now % 1000;
        args.put("call_id", ms + "." + nano);

        //args.put("call_id", "1288000053.9404");

        signRequest(args);
    }

    public void signRequest(HashMap<String, String> args) {
        if (args.containsKey("sig")) {
            args.remove("sig");
        }
        String sig = "";
        Object[] arrKey = args.keySet().toArray();
        Arrays.sort(arrKey);
        for (int i = 0; i < arrKey.length; i++) {
            String k = (String)arrKey[i];
            sig += k + "=" + args.get(k);
        }
        sig += secret;
        //System.out.println(" signature : " + sig + "!");
        args.put("sig", encryptMD5(sig));
    }


    public String sendRequest(HashMap<String, String> args) throws CSocialControllerException {

        try {
            HttpClient httpclient = new DefaultHttpClient();

            String urlcoded = encode(args);
            // System.err.println(" API : " + api + "?" + urlcoded);
            HttpPost httpget = new HttpPost(api + "?" + urlcoded);
            //HttpGet httpget = new HttpGet("http://dev.openapi2.me.zing.vn/api/sessions?" +  encode(args) );
            HttpResponse response = httpclient.execute(httpget);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                //  System.out.println( entity.getContentLength());
                byte[] arr = new byte[(int)entity.getContentLength()];
                InputStream instream = entity.getContent();
                instream.read(arr);
                String result = new String(arr);
                //  System.out.println(result);
                return result;
            }
            return null;
        } catch (Exception e) {
            CCommonHandler.writeErrLog(e);
            throw new CSocialControllerException(-1, " loi ");
        }

    }


    protected static String encode(HashMap<String, String> args) {
        String result = "";
        Object[] arrKey = args.keySet().toArray();
        Arrays.sort(arrKey);
        for (int i = 0; i < arrKey.length; i++) {
            //  for (int i = arrKey.length-1; i >=0; i--){
            String k = (String)arrKey[i];
            try {
                result +=
                        k + "=" + URLEncoder.encode(args.get(k), "UTF-8") + "&";
            } catch (UnsupportedEncodingException e) {
                CCommonHandler.writeErrLog(e);
            }
        }
        result = removeCharAt(result, result.length() - 1);
        // System.out.println( " result  =  "  +  result + "!");
        return result;
    }

    private static String removeCharAt(String s, int pos) {
        StringBuffer buf = new StringBuffer(s.length() - 1);
        buf.append(s.substring(0, pos)).append(s.substring(pos + 1));
        return buf.toString();
    }

    private String parseRespone(String respone) throws CSocialControllerException {
        try {
            // System.err.println(" respone :   " + respone );
            JSONObject data;
            data = new JSONObject(respone);
            return data.getString("data");
        } catch (JSONException e) {
            throw new CSocialControllerException(-2, " loi ");
            // TODO
        }
    }
}


